#!perl
use strict;
use CGI;
use DateTime;
use DateTime::Format::Mail;
use Digest::MD5 qw(md5_hex);
use Encode;
use File::stat;
use File::Basename;
use File::Find::Rule;
use MIME::Types;
use URI::Escape;
use Template;

# File path where you store your media files in
our $MediaPath    = "G:";

# External web server (e.g. Apache, lighttpd) that mounts $MediaPath
our $WebServer    = "http://10.0.1.2/ext";

# Local Filesystem encoding. cp932 for Windows XP Japanese, utf-8 for Mac
our $FileEncoding = "cp932";

# File Extension to serve in RSS feed
our @Extensions   = qw( avi divx mov flv wmv mp4 mpg mpeg mkv );

# Directory path to cache thumbnail images in
our $ThumbPath    = "Thumbs";

# Path to ffmpeg command. Used to generate thumbnails
our $FFmpeg       = "C:/FFMpeg/ffmpeg.exe";

my $query = CGI->new;

my $re    = "\.(" . join("|", @Extensions) . ')$';
my @files = File::Find::Rule->file->name( qr/$re/ )->in($MediaPath);

my @media;
for my $file (@files) {
    push @media, media_data(decode($FileEncoding, $file));
}

@media = sort { $b->{mtime} <=> $a->{mtime} } @media;

if ($ENV{GATEWAY_INTERFACE}) {
#    print CGI::header('application/rss+xml');
    print $query->header('text/xml');
}

binmode STDOUT, ":utf8";
my $format = DateTime::Format::Mail->new;

my $stash = {
    media => \@media,
    path => $MediaPath,
    webserver => $WebServer,
    rfc822 => sub { $format->format_datetime($_[0]) },
};

my $tmpl = join '', <DATA>;
my $tt   = Template->new;
$tt->process(\$tmpl, $stash) or die $tt->error;

sub media_data {
    my $file = shift;
    my $base = File::Basename::basename($file, map ".$_", @Extensions);
    my $dir  = File::Basename::dirname($file);
    $dir  =~ s!^$MediaPath/!!;
    return if $dir =~ /^Recycle[dr]/i or $dir =~ /System Volume Information/;

    $base =~ s/_/ /g;
    $dir  =~ s/_/ /g;

    if ($dir && $base !~ /\Q$dir\E/) {
        $base = "$dir - $base";
    }

    my $tag_re = decode_utf8('[\[\(【]([^\)\]】]*)[\)\]】]');
    my @tags;
    while ( $base =~ s/^$tag_re\s*|\s*$tag_re\.?$// ) {
        push @tags, $1 || $2;
    }

    my $thumb = md5_hex( encode_utf8($file) ) . ".jpg";
    my $thumb_path = $MediaPath . "/" . $ThumbPath . "/" . $thumb;
    if (!-e $thumb_path) {
        create_thumb($file, $thumb_path);
    }

    my $stat = stat( encode($FileEncoding, $file) );
    my $date = DateTime->from_epoch( epoch => $stat->mtime );
    my $url  = URI::Escape::uri_escape_utf8($file, "^A-Za-z0-9\-_.!~*'():/");
    $url =~ s!^$MediaPath/!$WebServer/!;

    my $ext  = ($file =~ /\.(\w+)$/)[0];
    my $types = MIME::Types->new;
    $types->addType(MIME::Type->new( type => 'video/flv', extensions => [ 'flv' ] ));
    $types->addType(MIME::Type->new( type => 'video/x-matroska', extensions => [ 'mkv' ] ));
    $types->addType(MIME::Type->new( type => 'video/subtitle', extensions => [ 'sub', 'srt' ] ));
    $types->addType(MIME::Type->new( type => 'video/divx', extensions => [ 'divx' ] ));

    my $mime = $types->mimeTypeOf($ext);
    $mime = $mime ? $mime->type : 'application/octet-stream';
    $base .= " (subtitle)" if $mime eq 'video/subtitle';

    return {
        path  => $file,
        title => $base,
        tags  => \@tags,
        mtime => $date,
        url   => $url,
        size  => $stat->size,
        type  => $mime,
        thumb => -s $thumb_path ? $WebServer . "/" . $ThumbPath . "/" . $thumb : undef,
    };
}

sub create_thumb {
    my($input, $thumb) = @_;

    my $file = encode($FileEncoding, $input);
    system(
        $FFmpeg,
        "-i", $file,
        '-f'       => 'image2',
        '-pix_fmt' => 'jpg',
        '-vframes' => 1,
        '-ss'      => 3,
        '-s'       => '704x396', # xxx to be configurable for 4:3 videos
        '-an',
        '-deinterlace',
        $thumb,
    );

    if (!-s $thumb) {
        open my $out, ">", $thumb; # create empty file
        close $out;
    }
}

__DATA__
<?xml version="1.0" encoding="UTF-8" ?> 
<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>Index of [% path | html %]</title>
<link>[% webserver | html %]</link>
[% FOREACH m = media %]
<item>
<title>[% m.title | html %]</title>
<link>[% m.url | html %]</link>
<pubDate>[% rfc822(m.mtime) | html %]</pubDate>
<guid>[% m.url | html %]</guid>
<media:content url="[% m.url | html %]" fileSize="[% m.size | html %]" medium="video" type="[% m.type | html %]">
<media:title type="plain">[% m.title | html %]</media:title>
<media:keywords>[% m.tags.join(', ') | html %]</media:keywords>
[% IF m.thumb %]<media:thumbnail url="[% m.thumb | html %]" />[% END %]
</media:content>
<enclosure url="[% m.url | html %]" type="[% m.type | html %]" length="[% m.size | html %]" />
</item>
[% END %]
</channel>
</rss>
